package com.ctakit.sdk.view;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.ctakit.sdk.view.annotation.LayoutContentId;
import com.ctakit.sdk.view.annotation.Onclick;
import com.ctakit.sdk.view.annotation.ViewInject;
import com.orhanobut.logger.Logger;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by imuto on 16/5/13.
 */
public class ViewInjector {


    private static final List<Class> IGNORES = new ArrayList<>();
    private static final List<String> IGNORES_PACKAGE_START = new ArrayList<>();

    static {
        IGNORES.add(Object.class);
        IGNORES_PACKAGE_START.add("android.");
    }

    public static void inject(View handler) {
        ViewFinder viewFinder = new ViewFinder(handler);
        injectFields(handler, viewFinder);
        injectMethod(handler, viewFinder);
    }

    public static void inject(Activity handler) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Class<?> handlerType = handler.getClass();
        int layoutId = initContentViewId(handlerType);
        if (layoutId > 0) {

                Method setContentView = handlerType.getMethod("setContentView", int.class);
                setContentView.invoke(handler, layoutId);
                ViewFinder viewFinder = new ViewFinder(handler);
                injectFields(handler, viewFinder);
                injectMethod(handler, viewFinder);

        }
    }

    public static void inject(Object handle, View from) {
        ViewFinder viewFinder = new ViewFinder(from);
        injectFields(handle, viewFinder);
        injectMethod(handle, viewFinder);
    }

    public static View inject(Object handler, LayoutInflater inflater, ViewGroup container) {
        View view = null;
        int layoutId = initContentViewId(handler.getClass());
        if (layoutId > 0) {
            view = inflater.inflate(layoutId, container, false);
        }
        return view;
    }

    public static void injectFields(Object handle, ViewFinder viewFinder) {

        if ( handle == null || viewFinder == null) {
            return;
        }


        Field[] fields = handle.getClass().getDeclaredFields(); // 获取字段
        if (fields != null) {

                for (Field field : fields) {
                      Class<?> fieldType = field.getType();
                    if (
                     Modifier.isStatic(field.getModifiers()) ||   // 不注入静态字段
                        Modifier.isFinal(field.getModifiers()) ||// 不注入final字段
                       fieldType.isPrimitive() || //不注入基本类型字段
                       fieldType.isEnum() || //不注入枚举类型字段
                       fieldType.isArray() ||  //不注入数组类型字段
                      fieldType == String.class) { //不注入String字段
                        continue;
                    }
                    ViewInject viewInject = field.getAnnotation(ViewInject.class);
                    if (viewInject != null) {
                        int viewId = viewInject.value();
                        field.setAccessible(true); // 设为可访问
                        try{
                        field.set(handle, viewFinder.find(viewId));
                    } catch (Exception ex) {
                            Logger.e("view :"+ex.getMessage());
                            throw new RuntimeException("view inject exception "+ex.getMessage());
                    }
                    }
                }

        }
    }


    public static void injectMethod(Object handle, ViewFinder finder) {
        if ( handle == null || finder == null) {
            return;
        }


        Method[] methods = handle.getClass().getDeclaredMethods();
        if (methods != null && methods.length > 0) {
            for (Method method : methods) {

                //检查当前方法是否是event注解的方法
                Onclick event = method.getAnnotation(Onclick.class);
                if (event != null) {
                    try {
                        // id参数
                        int value = event.value();


                        //循环所有id，生成ViewInfo并添加代理反射

                            if (value > 0) {
                                ViewInfo info = new ViewInfo();
                                info.value = value;
                                method.setAccessible(true);
                                EventListenerManager.addEventMethod(finder, info, EventListenerManager.ClickMethod.Click, handle, method);

                        }
                    } catch (Exception ex) {
                        Logger.e("view :"+ex.getMessage());
                        throw new RuntimeException("view inject exception "+ex.getMessage());
                    }
                }
            }
        }
    }

    private static int initContentViewId(Class<?> clazz) {
        LayoutContentId layoutContentId = findLayoutContentId(clazz);
        if (layoutContentId != null) {
            return layoutContentId.value();
        }
        return 0;
    }

    private static LayoutContentId findLayoutContentId(Class cls) {

        if (cls.isAnnotationPresent(LayoutContentId.class)) {
            return (LayoutContentId) cls.getAnnotation(LayoutContentId.class);
        }
        return null;
    }

}
